﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestByWire.Tutorial.Domain;

namespace TestByWire.Tutorial
{
	[TestClass]
    [UseStub(typeof(IEmployeStorage), typeof(MyStorage))]
    public class ControllingDependencies : TestTarget<SalaryManagerHardCoupled>
    {
        [TestMethod]
        public void DependencyIsReplacedWithStub()
        {
            When.Calling.EmptyCall();

            Then<IEmployeStorage>.Fulfills(x => x is MyStorage);
        }

        [TestMethod]
        [UseStub(typeof(IEmployeStorage), typeof(MyStorage2))]
        public void LocalDependencyDefinitionsOverrideGlobalDefinitions()
        {
            When.Calling.EmptyCall();

            Then<IEmployeStorage>.Fulfills(x => x is MyStorage2);
        }

        [UseStubLateBound(typeof(ITaxationCalulator), "_taxCalculator")]
        public void UseLateboundStubDirectlyOnField()
        {
            When.Calling.EmptyCall();

            Then<ITaxationCalulator>.Fulfills(x => x.GetType() != typeof(MyHardCoupling));
        }

		[UseStubLateBound(typeof(ITaxationCalulator), "_taxCalculator")]
        public void LateBoundStubsCanBeRegisteredOnName()
        {
            When.Calling.EmptyCall();

            Then<ITaxationCalulator>.Fulfills("_taxCalculator", x => x.GetType() != typeof(MyHardCoupling));
        }

    }

    public class MyStorage2 : MyStorage { }

	public class MyStorage : IEmployeStorage
    {
        public EmployeInformation RetrieveCurrentSalary(string employeeId)
        {
            return new EmployeInformation();
        }

        public void UpdateSalary(EmployeInformation employeInformation, double newSalary)
        {

        }
    }

    public class SalaryManagerHardCoupled : SalaryManager
    {
        public SalaryManagerHardCoupled(IEmployeStorage storage, ISalaryIndex salaryIndex, IEventRaiser eventRaiser)
            : base(storage, salaryIndex, new MyHardCoupling(), eventRaiser)
        {
        }

        public void EmptyCall()
        {
        }
    }

	public class MyFakeStorage : IEmployeStorage
	{
		public EmployeInformation RetrieveCurrentSalary(string employeeId)
		{
			return new EmployeInformation() { Salary = 100 };
		}

		public void UpdateSalary(EmployeInformation employeInformation, double newSalary)
		{
		}
	}

	public class MyOtherFakeStorage : IEmployeStorage
	{
		public EmployeInformation RetrieveCurrentSalary(string employeeId)
		{
			return new EmployeInformation() { Salary = 200 };
		}

		public void UpdateSalary(EmployeInformation employeInformation, double newSalary)
		{
		}
	}

    public class MyHardCoupling : ITaxationCalulator
    {
        public double CalculateTax(double saleryAdjustment)
        {
            return 1000000;
        }
    }
}
